package run.halo.app.aspect;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import run.halo.app.mail.MailService;
import run.halo.app.model.params.MailParam;

/**
 * @author zhangshirui
 * @date 2022.04.19
 */
@Aspect
@Component
public class ResponseTimeAspect {

    @Autowired
    MailService mailService;

    @Value("${mail.admin-address}")
    private String adminAddress;

    public static final Logger log = LoggerFactory.getLogger(ResponseTimeAspect.class);


    /**
     * 环绕通知 监控接口执行时间
     * ***切入点表达式的格式：
     * 	execution([修饰符] 返回值类型 包名.类名.方法名(参数))
     * 	** execution：必须要
     * 	** 修饰符：可省略
     * 	** 返回值类型：必须要，但是可以使用*通配符
     * 	** 包名	：
     * 		** 多级包之间使用.分割
     * 		** 包名可以使用*代替，多级包名可以使用多个*代替
     * 		** 如果想省略中间的包名可以使用 ..
     * 	** 类名
     * 		** 可以使用*代替
     * 		** 也可以写成*DaoImpl
     * 	** 方法名：
     * 		** 也可以使用*好代替
     * 		** 也可以写成add*
     * 	** 参数：
     * 		** 参数使用*代替
     * 		** 如果有多个参数，可以使用 ..代替
     * @param joinPoint
     * @return
     */
//    @Around("execution(* com.sun.foodie.controller..*.*(..))")
//    @Around("execution(* *..*.*Controller.*(..))")
    @Around("execution(* *..*.*Controller.*(..))")
    public Object recordTimeLog (ProceedingJoinPoint joinPoint) throws Throwable {
        log.info("====== 开始执行 {}.{} ======",
                joinPoint.getTarget().getClass(),
                joinPoint.getSignature().getName());

        // 记录开始时间
        long begin = System.currentTimeMillis();

        // 执行目标 service
        Object result = joinPoint.proceed();

        // 记录结束时间
        long end = System.currentTimeMillis();
        long takeTime = end - begin;

        String target = joinPoint.getTarget().getClass().toString() + "." + joinPoint.getSignature().getName();
        if (takeTime > 500) {
            MailParam mailParam = new MailParam();
            mailParam.setTo(adminAddress);
            mailParam.setSubject("接口延迟警告");
            mailParam.setContent("接口" + target + "耗时:" + takeTime + "ms, 超过500ms!!!");
            log.error("====== {}.{} 执行结束，耗时：{} 毫秒 ======", joinPoint.getTarget().getClass(), joinPoint.getSignature().getName(), takeTime);
            mailService.sendTextMail(mailParam.getTo(), mailParam.getSubject(), mailParam.getContent());
        } else if (takeTime > 300) {
            log.warn("====== {}.{} 执行结束，耗时：{} 毫秒 ======", joinPoint.getTarget().getClass(), joinPoint.getSignature().getName(), takeTime);
        } else {
            log.info("====== {}.{} 执行结束，耗时：{} 毫秒 ======", joinPoint.getTarget().getClass(), joinPoint.getSignature().getName(), takeTime);
        }
        return result;
    }
}
